package com.greensam.pixelengine.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.greensam.pixelengine.constant.KeyValueStorageConstant;
import com.greensam.pixelengine.pojo.base.PaginationResponse;
import com.greensam.pixelengine.pojo.emuns.PicturePixelEnum;
import com.greensam.pixelengine.pojo.entity.PicturePo;
import com.greensam.pixelengine.pojo.entity.QPicturePo;
import com.greensam.pixelengine.pojo.query.PicturePageQuery;
import com.greensam.pixelengine.repository.PictureRepository;
import com.greensam.pixelengine.service.PictureDataService;
import com.greensam.pixelengine.service.kv.KVStore;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author Macro_Ray
 * @since 2025/7/2 15:37
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PictureDataServiceImpl implements PictureDataService {

    private final KVStore kvStore;
    private final JPAQueryFactory jpaQueryFactory;
    private final PictureRepository pictureRepository;

    @Override
    public Optional<PicturePo> getPictureById(Long pictureId) {
        return pictureRepository.findByIdAndDelete(pictureId, Boolean.FALSE);
    }

    @Override
    public PicturePo save(PicturePo picturePo) {
        if (Objects.isNull(picturePo)) {
            return null;
        }
        return pictureRepository.save(picturePo);
    }

    @Override
    public PaginationResponse<PicturePo> pagePicture(PicturePageQuery pageQuery) {
        QPicturePo p = QPicturePo.picturePo;

        BooleanBuilder condition = new BooleanBuilder();
        condition.and(p.delete.eq(Boolean.FALSE));
        if (StringUtils.isNotBlank(pageQuery.getCategory())) {
            condition.and(p.category.eq(pageQuery.getCategory()));
        }
        if (StringUtils.isNotBlank(pageQuery.getTag())) {
            condition.and(p.tags.eq(pageQuery.getTag()));
        }
        if (CollectionUtil.isNotEmpty(pageQuery.getTags())) {
            condition.and(p.tags.in(pageQuery.getTags()));
        }
        if (Objects.nonNull(pageQuery.getReviewStatus())) {
            condition.and(p.reviewStatus.eq(pageQuery.getReviewStatus()));
        }
        if (pageQuery.getIsPublic()) {
            condition.and(p.spaceId.isNull());
        } else if (Objects.nonNull(pageQuery.getSpaceId())) {
            condition.and(p.spaceId.eq(pageQuery.getSpaceId()));
        }
        if (Objects.nonNull(pageQuery.getStartTime()) && Objects.nonNull(pageQuery.getEndTime())) {
            condition.and(p.updateTime.between(pageQuery.getStartTime(), pageQuery.getEndTime()));
        }
        if (StringUtils.isNotBlank(pageQuery.getPicFormat())) {
            condition.and(p.picFormat.eq(pageQuery.getPicFormat()));
        }
        PicturePixelEnum queryPixel = pageQuery.getQueryPixel();
        NumberExpression<Integer> picPixel = (p.picWidth.intValue()).multiply(p.picHeight.intValue());
        if (Objects.nonNull(queryPixel)) {
            if (!PicturePixelEnum.CUSTOM.equals(queryPixel)) {
                Integer minPixel = queryPixel.getMinPixel();
                Integer maxPixel = queryPixel.getMaxPixel();
                condition.and(picPixel.between(minPixel, maxPixel));
            } else if (Objects.nonNull(pageQuery.getPicHeight()) && Objects.nonNull(pageQuery.getPicWidth())) {
                condition.and(picPixel.goe(pageQuery.getPicWidth() * pageQuery.getPicHeight()));
            }
        }

        if (StringUtils.isNotBlank(pageQuery.getKeyword())) {
            condition.and(p.name.containsIgnoreCase(pageQuery.getKeyword()))
                    .or(p.description.containsIgnoreCase(pageQuery.getKeyword()))
                    .or(p.createName.containsIgnoreCase(pageQuery.getKeyword()));
        }

        Long totalCount = jpaQueryFactory.select(p.id.countDistinct())
                .from(p)
                .where(condition)
                .fetchOne();
        if (Objects.isNull(totalCount) || totalCount == 0) {
            return PaginationResponse.empty(pageQuery.getPageSize(), pageQuery.getPageNum());
        }

        List<PicturePo> result = jpaQueryFactory.selectFrom(p)
                .where(condition)
                .orderBy(p.updateTime.desc())
                .offset(pageQuery.offset())
                .limit(pageQuery.getPageSize())
                .fetch();

        return PaginationResponse.page(result, totalCount, pageQuery.getPageSize(), pageQuery.getPageNum());
    }

    @Override
    public String getPictureVoCache(String key) {
        if (StringUtils.isBlank(key)) {
            return "";
        }
        return kvStore.get(key);
    }

    @Override
    public void savePictureVoCache(String key, String cacheValue) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(cacheValue)) {
            return;
        }
        kvStore.set(key, cacheValue, KeyValueStorageConstant.EXPIRE_TIME);
    }

    @Override
    public List<PicturePo> listPicture(Long spaceId, Boolean isPublic) {
        QPicturePo p = QPicturePo.picturePo;

        BooleanBuilder condition = new BooleanBuilder();
        condition.and(p.delete.eq(Boolean.FALSE));
        // 查询所有图片时不对空间id进行限制
        if (isPublic) {
            // 查询公共空间
            condition.and(p.spaceId.isNull());
        } else if (Objects.nonNull(spaceId)) {
            // 不是公共空间且传了空间id -> 查询私有空间
            condition.and(p.spaceId.eq(spaceId));
        }

        return jpaQueryFactory.selectFrom(p)
                .where(condition)
                .fetch();
    }
}
